class Delta  {
    constructor(ops = []) {
        if (Array.isArray(ops)) {
            this.ops = ops;
        } else if (ops != null && Array.isArray(ops.ops)) {
            this.ops = ops.ops;
        } else {
            this.ops = [];
        }
    }

    /**
     * 插入文本操作
     * @param text
     * @param attributes
     * @returns {*|Delta}
     */
    insert(text, attributes = {}){
        const newOp = {};
        if (text.length === 0) return this;
        newOp.insert = text;
        if (attributes != null && typeof attributes === 'object' && Object.keys(attributes).length > 0) {
            newOp.attributes = attributes;
        }
        return this.ops.push(newOp);
    }

    /**
     * 删除对应文本的操作
     * @param text
     * @param attributes
     */
    delete(text,attributes = {} ){

    }
}


/**
 * 编辑器
 */
class MyEditor {
    constructor() {
        /*delta*/
        this.delta = new Delta();
        /*编辑器*/
        this.editor = document.querySelector('#editor');
        /*工具栏*/
        this.toolbar = document.querySelector('.toolbar');
        /*初始事件*/
        this.init();
    }

    /*初始事件*/
    init(){
        /*工具栏的事件*/
        this.toolbarEvent();
        /*编辑框的事件*/
        this.editorEvent();
        /*初始化editor的内容状态*/
        // this.updatePlaceholder();
    }


    /**
     * 工具栏的事件
     */
    toolbarEvent(){
        this.toolbar.addEventListener('click', (e) => {
            const button = e.target.closest('button');
            if (!button) return;

            const command = button.dataset.command;
            if (command) {
                this.formatStyle(command);
            }
        });
    }

    /**
     * 编辑框的事件
     */
    editorEvent(){
        /*监听输入事件*/
        // this.editor.addEventListener('input', (e)=>{
        //     this.updatePlaceholder(e);
        // });
        // /*监听blur事件*/
        // this.editor.addEventListener('blur', (e)=>{
        //     this.updatePlaceholder(e);
        // });
        // /*监听focus事件*/
        // this.editor.addEventListener('focus', (e)=>{
        //     this.updatePlaceholder(e);
        // });
    }


    // /**
    //  * 更新编辑框状态
    //  */
    // updatePlaceholder(){
    //     /*判断编辑框的内容是否为空*/
    //     const isEmpty = this.editor.textContent.trim() === '' &&  this.editor.children.length === 0;
    //     const hasOnlyEmptyTags =  this.editor.children.length === 1 &&
    //         ( this.editor.firstElementChild.tagName === 'P' ||  this.editor.firstElementChild.tagName === 'BR') &&
    //         this.editor.firstElementChild.textContent.trim() === '';
    //     if (isEmpty || hasOnlyEmptyTags) {
    //         this.editor.classList.remove('has-content');
    //     } else {
    //         this.editor.classList.add('has-content');
    //     }
    // }


    /**
     * 在应用加粗之前，我们需要确定选定内容是否已经加粗
     * @param range
     * @param styleType
     */
    isSelectionStyle(range,styleType){
        // 获取选区的父节点（通常是包含被选中文本的最近的HTML元素）
        let commonAncestorContainer = range.commonAncestorContainer;
        // 如果commonAncestorContainer是文本节点，则获取其父元素
        if (commonAncestorContainer.nodeType === Node.TEXT_NODE) {
            /*获取父元素*/
            commonAncestorContainer = commonAncestorContainer.parentNode;
            /*如果父组件已经有html标签*/
            if (commonAncestorContainer.tagName.toLowerCase() === styleType ){
                return true;
            }
        }



        //
        // const commonAncestor = range.commonAncestorContainer;
        // // 检查共同祖先本身是否加粗
        // if (commonAncestor.nodeType === Node.ELEMENT_NODE && commonAncestor.tagName === styleType ) {
        //     return true;
        // }

        // 检查共同祖先的任何父级是否加粗，直到编辑器边界
        // let currentNode = commonAncestor;
        // while (currentNode && currentNode!== this.editor) {
        //     if (currentNode.nodeType === Node.ELEMENT_NODE &&
        //         (currentNode.tagName === styleType )) {
        //         return true;
        //     }
        //     currentNode = currentNode.parentNode;
        // }

        // 如果选区跨越多个节点，检查所有选定节点是否加粗
        // 这是一个更复杂的检查，为简化起见，我们假设共同祖先检查就足够了
        // 或者 surroundContents 将通过创建新的加粗标签来处理它。
        // 对于健壮的解决方案，需要遍历范围内的所有节点。
        return false;
    }

    /**
     * 添加样式
     * @param command
     */
    formatStyle(command){
        let  styleType = '';
        switch (command){
            case 'bold':
                styleType = 'strong';
                break;
            case 'underline':
                styleType = 'u';
                break;
            case 'italic':
                styleType = 'em';
                break;
            case 'strikeThrough':
                styleType = 's';
                break;
        }
        /*获取当前框选的选区*/
        const selection = window.getSelection();
        /*如果没有选区*/
        // 如果没有文本被选中，或者选中范围为空
        if (!selection || selection.rangeCount === 0) {
            return ;
        }

        // 获取选区中的第一个范围
        const range = selection.getRangeAt(0);

        /*获取临界点*/
        const rect = range.getBoundingClientRect();
        if (rect){
            const {right} = rect;
            console.log(right,'11111111111111111111ddddddddddddddddddddddddddddddd')
        }

        console.log(range,'ddddddddddddddddddddd')

        /*获取被选中的文本*/
        const selectStr = range.toString();
        // 2. 遍历克隆的内容
        let foundStrong = false; // 标记是否找到了<strong>标签

        // commonAncestorContainer 是包含选区所有内容的最近的共同祖先节点。
        // 如果是文本节点，我们通常需要它的父元素。
        let commonAncestorContainer = range.commonAncestorContainer;
        if (commonAncestorContainer.nodeType === Node.TEXT_NODE) {
            /*获取父元素*/
            commonAncestorContainer = commonAncestorContainer.parentNode;
            /*如果父组件已经有html标签*/
            if (commonAncestorContainer.tagName.toLowerCase() === styleType ){
                const parentElement = commonAncestorContainer.parentElement;
                // 如果已被包裹，则移除标签
                const textNode = document.createTextNode(selectStr);
                parentElement.parentNode.replaceChild(textNode, parentElement);
                console.log(selectStr,'selectStrselectStrselectStr')
            }else {

            }
        }


        // 1. 克隆选区内容，避免直接修改DOM导致选区失效
        const clonedContents = range.cloneContents();

        // 创建一个新的文档片段，用于存放处理后的内容
        const processedFragment = document.createDocumentFragment();

        function processNode(node) {
            if (node.nodeType === Node.ELEMENT_NODE && node.tagName.toLowerCase() === styleType) {
                // 如果是<strong>标签，将它的所有子节点（文本或其他标签）添加到新的片段中
                while (node.firstChild) {
                    processedFragment.appendChild(node.firstChild);
                }
                foundStrong = true;
            } else if (node.nodeType === Node.TEXT_NODE) {
                // 如果是文本节点，直接添加到新的片段中
                processedFragment.appendChild(node.cloneNode(true));
            } else {
                // 如果是其他元素节点，递归处理其子节点
                const clonedNode = node.cloneNode(false); // 只克隆节点本身，不克隆子节点
                while (node.firstChild) {
                    clonedNode.appendChild(processNode(node.firstChild)); // 递归处理并添加子节点
                }
                processedFragment.appendChild(clonedNode);
            }
            return node; // 返回原节点，供递归处理
        }

        // 遍历克隆的内容，处理其中的所有节点
        for (let i = 0; i < clonedContents.childNodes.length; i++) {
            let $_childNode = clonedContents.childNodes[i];
            // console.log($_childNode,'dddddddddddddddddddddddddddddd')
            processNode($_childNode);
        }


        // console.log(foundStrong,'foundStrong')
        // 如果选区内容中包含<strong>标签，则进行替换
        if (foundStrong) {
            // 3. 删除原始选区的内容
            range.deleteContents();

            // 4. 将处理后的内容插入到原始选区的位置
            range.insertNode(processedFragment);

            // 清除选区，或者根据需要重新设置选区
            // selection.empty(); // 或者 selection.removeAllRanges();
        } else {
            console.log("选中的文本中没有发现<strong>标签。");
            /*创建格式化标签*/
            const $dom = document.createElement(styleType);
            /* range.extractContents(): 将Range所代表的文档片段从DOM树中提取（“剪切”）出来，并返回一个 DocumentFragment。这个DocumentFragment包含了所有被选中的节点。因为是“提取”，所以原位置的内容会被删除*/
            $dom.appendChild(range.extractContents());
            /*range.insertNode(node): 在Range（框选区）的起始位置插入一个我们指定的DOM节点（新的格式化标签）。*/
            range.insertNode($dom);

            /*把当前操作的节点信息加入到delta*/
            this.delta.insert(selectStr, {[command]: true});
        }

        console.log(this.delta,'pppppppppppppppppppppppp')























        return;
        /*获取当前选区是否有该样式*/
        const currentStyle = this.isSelectionStyle(range,styleType);
        // // 1. 克隆选区内容，避免直接修改DOM导致选区失效
        // const clonedContents = range.cloneContents();


        // 遍历克隆的内容，处理其中的所有节点
        for (let i = 0; i < clonedContents.childNodes.length; i++) {
            this.processNode(clonedContents.childNodes[i]);
        }

        if (currentStyle) {

            console.log(selectStr,'存在标签rrrrrrrrrrrrrrrrrrrrrrrrrrrrrr')

        } else {
            console.log(currentStyle,'ssssssssssssssssssss')
            /*创建格式化标签*/
            const $dom = document.createElement(styleType);
            /* range.extractContents(): 将Range所代表的文档片段从DOM树中提取（“剪切”）出来，并返回一个 DocumentFragment。这个DocumentFragment包含了所有被选中的节点。因为是“提取”，所以原位置的内容会被删除*/
            $dom.appendChild(range.extractContents());
            /*range.insertNode(node): 在Range（框选区）的起始位置插入一个我们指定的DOM节点（新的格式化标签）。*/
            range.insertNode($dom);

            /*把当前操作的节点信息加入到delta*/
            this.delta.insert(selectStr, {[command]: true});
        }

        return;
        /*创建格式化标签*/
        const $dom = document.createElement(styleType);
        /* range.extractContents(): 将Range所代表的文档片段从DOM树中提取（“剪切”）出来，并返回一个 DocumentFragment。这个DocumentFragment包含了所有被选中的节点。因为是“提取”，所以原位置的内容会被删除*/
        $dom.appendChild(range.extractContents());
        /*range.insertNode(node): 在Range（框选区）的起始位置插入一个我们指定的DOM节点（新的格式化标签）。*/
        range.insertNode($dom);

        /*把当前操作的节点信息加入到delta*/
        this.delta.insert(selectStr, {[command]: true});

        console.log(this.delta,'dddddddddddddddddddddd')
    }

    /**
     * 递归处理并添加子节点
     * @param node
     * @returns {*}
     */
    processNode(node) {
        // 创建一个新的文档片段，用于存放处理后的内容
        const processedFragment = document.createDocumentFragment();
        // 2. 遍历克隆的内容
        let foundStrong = false; // 标记是否找到了<strong>标签
        if (node.nodeType === Node.ELEMENT_NODE && node.tagName.toLowerCase() === 'strong') {
            // 如果是<strong>标签，将它的所有子节点（文本或其他标签）添加到新的片段中
            while (node.firstChild) {
                processedFragment.appendChild(node.firstChild);
            }
            foundStrong = true;
        } else if (node.nodeType === Node.TEXT_NODE) {
            // 如果是文本节点，直接添加到新的片段中
            processedFragment.appendChild(node.cloneNode(true));
        } else {
            // 如果是其他元素节点，递归处理其子节点
            const clonedNode = node.cloneNode(false); // 只克隆节点本身，不克隆子节点
            while (node.firstChild) {
                clonedNode.appendChild(this.processNode(node.firstChild)); // 递归处理并添加子节点
            }
            processedFragment.appendChild(clonedNode);
        }

        console.log(foundStrong,'foundStrong')
        return node; // 返回原节点，供递归处理
    }
}

// 初始化编辑器
window.onload = function (){
    new MyEditor();
}
